using System.Collections.Generic;
using UnityEngine;

public class AIPlayer : BasePlayer
{
	protected class AICollector
	{
		private AIPlayer player;

		public AICollector(AIPlayer _player)
		{
			player = _player;
		}

		public CollectedMessage Collect()
		{
			CollectedMessage collectedMessage = new CollectedMessage();
			if (player.m_TargetBalls.Count == 0)
			{
				collectedMessage.ballList = Pools.GetSolidAndStripeBalls();
			}
			else
			{
				collectedMessage.ballList = player.m_TargetBalls;
			}
			if (collectedMessage.ballList.Count == 0)
			{
				UnityEngine.Debug.LogError("msg balllist count is zero!");
			}
			return collectedMessage;
		}
	}

	protected class CollectedMessage
	{
		public List<PoolBall> ballList;

		public CollectedMessage()
		{
			ballList = new List<PoolBall>();
		}
	}

	protected class AIDecider
	{
		private enum UpOrDown
		{
			Up = 1,
			Down = -1
		}

		private enum TableBorder
		{
			None,
			TopLeft,
			TopRight,
			Right,
			BottomRight,
			BottomLeft,
			Left
		}

		public AIPlayer player;

		private CollectedMessage cMsg;

		public AIDecider(AIPlayer _player)
		{
			player = _player;
		}

		public DecidedMessage Decide(CollectedMessage _cMsg)
		{
			cMsg = _cMsg;
			DecidedMessage decidedMessage = new DecidedMessage();
			Dictionary<PoolBall, List<PocketTrigger>> considerBalls = GetConsiderBalls();
			List<KeyValuePair<PoolBall, Vector3>> shootableBalls = GetShootableBalls();
			decidedMessage.drag = (GameManager.Rules.State == GlobalState.DRAG_WHITEBALL);
			decidedMessage.considerBalls = considerBalls;
			decidedMessage.shootableBalls = shootableBalls;
			PoolBall targetBall;
			PocketTrigger targetTrigger;
			if (decidedMessage.drag)
			{
				if (!GameManager.Rules.firstRound)
				{
					decidedMessage.hitPoint = ConsiderHitPointWithDrag(considerBalls, out decidedMessage.cueballPosition, out targetBall, out targetTrigger);
				}
				else
				{
					decidedMessage.hitPoint = Vector3.zero;
					targetBall = null;
					targetTrigger = null;
				}
			}
			else
			{
				decidedMessage.cueballPosition = Pools.CueBall.GetPosition();
				decidedMessage.hitPoint = ConsiderHitPoint(considerBalls, decidedMessage.cueballPosition, out targetBall, out targetTrigger);
			}
			if (decidedMessage.hitPoint != Vector3.zero)
			{
				decidedMessage.targetBall = targetBall;
				decidedMessage.targetPocket = targetTrigger;
				decidedMessage.powerScale = ConsiderPowerScale(targetBall, targetTrigger, decidedMessage.hitPoint, decidedMessage.cueballPosition);
			}
			else
			{
				Vector3 zero = Vector3.zero;
				PoolBall targetBall2 = null;
				if (canReboundHit && (zero = GetReboundHitPoint()) != Vector3.zero)
				{
					UnityEngine.Debug.Log("rebound!");
					decidedMessage.hitPoint = zero;
				}
				else if (canReboundPocket && (zero = GetReboundHitBall(out targetBall2)) != Vector3.zero)
				{
					decidedMessage.targetBall = targetBall2;
					decidedMessage.hitPoint = zero;
				}
				else if (decidedMessage.shootableBalls.Count != 0)
				{
					int index = Mathf.Max(Random.Range(0, decidedMessage.shootableBalls.Count - 1), 0);
					decidedMessage.targetBall = decidedMessage.shootableBalls[index].Key;
					decidedMessage.hitPoint = decidedMessage.shootableBalls[index].Value;
				}
				else
				{
					int index2 = Mathf.Max(Random.Range(0, cMsg.ballList.Count - 1));
					decidedMessage.targetBall = cMsg.ballList[index2];
					decidedMessage.hitPoint = decidedMessage.targetBall.transform.position;
				}
				int index3 = Random.Range(0, Pools.PocketTriggers.Count - 1);
				decidedMessage.targetPocket = Pools.PocketTriggers[index3];
				if (GameManager.Rules.firstRound)
				{
					decidedMessage.cueballPosition = ConsiderCueballPositionAtFirstRound();
				}
				else
				{
					decidedMessage.cueballPosition = Pools.CueBall.GetPosition();
				}
				decidedMessage.powerScale = 1f;
			}
			if (BaseUIController.Instance.debugAI)
			{
				BaseUIController.Instance.targetBallImage.transform.position = MathTools.World2UI(decidedMessage.targetBall.transform.position);
				BaseUIController.Instance.targetPocketImage.transform.position = MathTools.World2UI(decidedMessage.targetPocket.transform.position);
				BaseUIController.Instance.hitPointImage.transform.position = MathTools.World2UI(decidedMessage.hitPoint);
			}
			player.m_Deviation = degreeOffset;
			decidedMessage.hitPoint += new Vector3(Random.Range(0f - player.m_Deviation, player.m_Deviation), 0f, Random.Range(0f - player.m_Deviation, player.m_Deviation));
			if (Random.Range(0, 100) > (int)difficulty)
			{
			}
			if (BaseUIController.Instance.debugAI)
			{
				BaseUIController.Instance.newHitPointImage.transform.position = MathTools.World2UI(decidedMessage.hitPoint);
			}
			return decidedMessage;
		}

		private Vector3 ConsiderHitPointWithDrag(Dictionary<PoolBall, List<PocketTrigger>> considerBalls, out Vector3 cueBallPosition, out PoolBall targetBall, out PocketTrigger targetTrigger)
		{
			Dictionary<PoolBall, PocketTrigger> dictionary = FilterTheBestPocketForEachBall(considerBalls);
			cueBallPosition = Vector3.zero;
			targetTrigger = null;
			targetBall = null;
			if (dictionary.Count == 0)
			{
				return Vector3.zero;
			}
			foreach (KeyValuePair<PoolBall, PocketTrigger> item in dictionary)
			{
				targetBall = item.Key;
				targetTrigger = item.Value;
				if ((bool)targetTrigger)
				{
					Vector3 bestPoint = targetTrigger.GetBestPoint(targetBall.transform.position);
					Vector3 vector = targetBall.transform.position - bestPoint;
					cueBallPosition = targetBall.transform.position + vector.normalized * Mathf.Min(GetPlacedSpace(targetBall, targetBall.transform.position - bestPoint), 5f * targetBall.GetRadius());
					if (Random.Range(1, dictionary.Count) == 1)
					{
						break;
					}
				}
			}
			if (!targetTrigger)
			{
				return Vector3.zero;
			}
			return SupportTools.GetHitPoint(targetBall, targetTrigger);
		}

		private Vector3 ConsiderCueballPositionAtFirstRound()
		{
			Constraint component = Pools.CueBall.GetComponent<Constraint>();
			Vector3 result = default(Vector3);
			Vector3 min = component.min;
			float x = min.x;
			Vector3 max = component.max;
			result.x = Random.Range(x, max.x);
			Vector3 min2 = component.min;
			float z = min2.z;
			Vector3 max2 = component.max;
			result.z = Random.Range(z, max2.z);
			return result;
		}

		private Dictionary<PoolBall, PocketTrigger> FilterTheBestPocketForEachBall(Dictionary<PoolBall, List<PocketTrigger>> considerBalls)
		{
			Dictionary<PoolBall, PocketTrigger> dictionary = new Dictionary<PoolBall, PocketTrigger>();
			foreach (KeyValuePair<PoolBall, List<PocketTrigger>> considerBall in considerBalls)
			{
				PoolBall key = considerBall.Key;
				float num = float.MaxValue;
				PocketTrigger value = null;
				int i = 0;
				for (int count = considerBall.Value.Count; i < count; i++)
				{
					PocketTrigger pocketTrigger = considerBall.Value[i];
					Vector3 bestPoint = pocketTrigger.GetBestPoint(key.transform.position);
					if (!(GetPlacedSpace(key, key.transform.position - bestPoint) < key.GetRadius() * 2f))
					{
						float num2 = Vector3.Distance(key.transform.position, bestPoint);
						if (num2 < num)
						{
							value = pocketTrigger;
							num = num2;
						}
					}
				}
				dictionary.Add(key, value);
			}
			return dictionary;
		}

		private Vector3 ConsiderHitPoint(Dictionary<PoolBall, List<PocketTrigger>> considerBalls, Vector3 cueBallPosition, out PoolBall targetBall, out PocketTrigger targetTrigger)
		{
			Dictionary<PoolBall, PocketTrigger> dictionary = FilterTheBestPocketForEachBallWithCueBall(considerBalls, cueBallPosition);
			List<float> list = new List<float>();
			List<PoolBall> list2 = new List<PoolBall>();
			float num = 0f;
			foreach (KeyValuePair<PoolBall, PocketTrigger> item in dictionary)
			{
				PoolBall key = item.Key;
				PocketTrigger value = item.Value;
				if ((bool)value)
				{
					float num2 = MathTools.AngleBetween(key.transform.position - cueBallPosition, value.GetBestPoint(key.transform.position) - key.transform.position);
					num2 = 90f - num2;
					num += num2;
					list2.Add(key);
					list.Add(num2);
				}
			}
			float num3 = Random.Range(0f, num);
			float num4 = 0f;
			int i = 0;
			for (int count = list.Count; i < count; i++)
			{
				num4 += list[i];
				if (num3 < num4)
				{
					targetTrigger = dictionary[targetBall = list2[i]];
					return SupportTools.GetHitPoint(targetBall, targetTrigger);
				}
			}
			targetTrigger = null;
			targetBall = null;
			return Vector3.zero;
		}

		private Dictionary<PoolBall, PocketTrigger> FilterTheBestPocketForEachBallWithCueBall(Dictionary<PoolBall, List<PocketTrigger>> considerBalls, Vector3 cueBallPosition)
		{
			Dictionary<PoolBall, PocketTrigger> dictionary = new Dictionary<PoolBall, PocketTrigger>();
			foreach (KeyValuePair<PoolBall, List<PocketTrigger>> considerBall in considerBalls)
			{
				PoolBall key = considerBall.Key;
				float num = 70f;
				PocketTrigger value = null;
				int i = 0;
				for (int count = considerBall.Value.Count; i < count; i++)
				{
					PocketTrigger pocketTrigger = considerBall.Value[i];
					if (!CheckObastacleBetweenTargetPositionAndCueball(key, SupportTools.GetHitPoint(key, pocketTrigger), cueBallPosition))
					{
						float num2 = MathTools.AngleBetween(key.transform.position - cueBallPosition, pocketTrigger.GetBestPoint(key.transform.position) - key.transform.position);
						if (num2 < num)
						{
							value = pocketTrigger;
							num = num2;
						}
					}
				}
				dictionary.Add(key, value);
			}
			return dictionary;
		}

		private float GetPlacedSpace(PoolBall ball, Vector3 dir)
		{
			ball.GetComponent<Collider>().enabled = false;
			ball.GetComponent<Rigidbody>().isKinematic = true;
			float result = 0f;
			if (Physics.SphereCast(ball.transform.position, ball.GetRadius(), dir, out RaycastHit hitInfo, ConstantData.OulineAndBallLayer))
			{
				result = (hitInfo.point - ball.transform.position).magnitude * 0.5f;
			}
			ball.GetComponent<Collider>().enabled = true;
			ball.GetComponent<Rigidbody>().isKinematic = false;
			return result;
		}

		private List<KeyValuePair<PoolBall, Vector3>> GetShootableBalls()
		{
			List<KeyValuePair<PoolBall, Vector3>> list = new List<KeyValuePair<PoolBall, Vector3>>();
			Vector3 position = Pools.CueBall.GetPosition();
			for (int i = 0; i < cMsg.ballList.Count; i++)
			{
				PoolBall poolBall = cMsg.ballList[i];
				Vector3 zero = Vector3.zero;
				if (poolBall.BallState != PoolBall.State.IDLE)
				{
					continue;
				}
				Vector3 vector = poolBall.transform.position - position;
				Vector2[] array = MathTools.PerpendicularVector2D(new Vector2(vector.x, vector.z));
				Vector3[] array2 = new Vector3[3]
				{
					poolBall.transform.position,
					poolBall.transform.position + new Vector3(array[0].x, 0f, array[0].y) * poolBall.GetRadius(),
					poolBall.transform.position + new Vector3(array[1].x, 0f, array[1].y) * poolBall.GetRadius()
				};
				foreach (Vector3 zero1 in array2)
				{
					if (!CheckObastacleBetweenTargetPositionAndCueball(poolBall, zero1, position))
					{
						list.Add(new KeyValuePair<PoolBall, Vector3>(poolBall, zero1));
						break;
					}
				}
			}
			return list;
		}

		private Dictionary<PoolBall, List<PocketTrigger>> GetConsiderBalls()
		{
			Dictionary<PoolBall, List<PocketTrigger>> dictionary = new Dictionary<PoolBall, List<PocketTrigger>>();
			for (int i = 0; i < cMsg.ballList.Count; i++)
			{
				PoolBall poolBall = cMsg.ballList[i];
				if (poolBall.BallState != PoolBall.State.IDLE)
				{
					continue;
				}
				List<PocketTrigger> list = new List<PocketTrigger>();
				for (int j = 0; j < Pools.PocketTriggers.Count; j++)
				{
					PocketTrigger pocketTrigger = Pools.PocketTriggers[j];
					if (!CheckObastacleBetweenBallAndPocket(poolBall, pocketTrigger))
					{
						list.Add(pocketTrigger);
					}
				}
				if (list.Count != 0)
				{
					dictionary.Add(poolBall, list);
				}
			}
			return dictionary;
		}

		private bool CheckObastacleBetweenBallAndPocket(PoolBall originBall, PocketTrigger pocket)
		{
			Vector3 direction = pocket.GetBestPoint(originBall.transform.position) - originBall.transform.position;
			RaycastHit[] array = Physics.SphereCastAll(originBall.transform.position, originBall.GetRadius(), direction, direction.magnitude, ConstantData.OulineAndBallLayer);
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit raycastHit = array2[i];
				if (raycastHit.collider.name.CompareTo(originBall.name) != 0)
				{
					return true;
				}
			}
			return false;
		}

		private bool CheckObastacleBetweenTargetPositionAndCueball(PoolBall ball, Vector3 targetPosition, Vector3 cueBallPosition)
		{
			Vector3 direction = targetPosition - cueBallPosition;
			RaycastHit[] array = Physics.SphereCastAll(cueBallPosition, Pools.CueBall.GetRadius(), direction, direction.magnitude, ConstantData.OulineAndBallLayer);
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit raycastHit = array2[i];
				if (raycastHit.collider.name.CompareTo(ball.name) != 0)
				{
					return true;
				}
			}
			return false;
		}

		private float ConsiderPowerScale(PoolBall ball, PocketTrigger trigger, Vector3 hitPoint, Vector3 cueBallPosition)
		{
			Vector3 position = ball.transform.position;
			Vector3 bestPoint = trigger.GetBestPoint(position);
			float num = (position - cueBallPosition).magnitude + (bestPoint - position).magnitude;
			float num2 = num;
			Vector2 tableSize = Pools.GetTableSize();
			return Mathf.Min(1f, num2 / tableSize.x);
		}

		private Vector3 GetRandomHitPoint()
		{
			int index = Random.Range(0, cMsg.ballList.Count - 1);
			int index2 = Random.Range(0, Pools.PocketTriggers.Count - 1);
			return SupportTools.GetHitPoint(cMsg.ballList[index], Pools.PocketTriggers[index2]);
		}

		public Vector3 GetReboundHitBall(out PoolBall targetBall)
		{
			targetBall = null;
			Vector3 vector = Vector3.zero;
			for (int i = 0; i < cMsg.ballList.Count; i++)
			{
				PoolBall poolBall = cMsg.ballList[i];
				if (poolBall.BallState != PoolBall.State.IDLE)
				{
					continue;
				}
				PocketTrigger closestPocket = GetClosestPocket(poolBall);
				if (closestPocket != null)
				{
					if (closestPocket.PocketIndex == PocketIndexes.TopCenter)
					{
						vector = GetRayReboundHitPoint(poolBall, UpOrDown.Up);
					}
					else if (closestPocket.PocketIndex == PocketIndexes.BottomCenter)
					{
						vector = GetRayReboundHitPoint(poolBall, UpOrDown.Down);
					}
					if (vector != Vector3.zero)
					{
						targetBall = poolBall;
					}
				}
			}
			return vector;
		}

		private PocketTrigger GetPocketTrigger(UpOrDown dir)
		{
			PocketIndexes pocketIndexes = PocketIndexes.None;
			switch (dir)
			{
				case UpOrDown.Up:
					pocketIndexes = PocketIndexes.BottomCenter;
					break;
				case UpOrDown.Down:
					pocketIndexes = PocketIndexes.TopCenter;
					break;
			}
			for (int i = 0; i < Pools.PocketTriggers.Count; i++)
			{
				PocketTrigger pocketTrigger = Pools.PocketTriggers[i];
				if (pocketTrigger.PocketIndex == pocketIndexes)
				{
					return pocketTrigger;
				}
			}
			return null;
		}

		private Vector3 GetRayReboundHitPoint(PoolBall ball, UpOrDown dir)
		{
			Ray ray = new Ray(ball.position, new Vector3(0f, 0f, 1f * (float)dir));
			UnityEngine.Debug.DrawRay(ray.origin, ray.direction, Color.yellow);
			if (Physics.SphereCast(ray, ball.GetRadius(), out RaycastHit hitInfo))
			{
				UnityEngine.Debug.Log("hit:" + hitInfo.transform.name);
				Vector3 point = hitInfo.point;
				float z = point.z;
				Vector3 position = ball.position;
				float num = Mathf.Abs(z - position.z);
				Vector3 a = point + new Vector3(0f, 0f, num * (float)dir);
				Vector3 realPosition = GetPocketTrigger(dir).GetRealPosition();
				Ray ray2 = new Ray(realPosition, a - realPosition);
				UnityEngine.Debug.DrawRay(ray2.origin, ray2.direction);
				if (Physics.Raycast(ray2, out RaycastHit hitInfo2))
				{
					string name = hitInfo2.transform.name;
					UnityEngine.Debug.Log("rebound hit:" + name);
					if (name.Contains("Rail_"))
					{
						string value = name.Substring(5);
						if (value.ToEnum(TableBorder.None) != 0)
						{
							return hitInfo2.point;
						}
					}
				}
			}
			return Vector3.zero;
		}

		private PocketTrigger GetClosestPocket(PoolBall ball)
		{
			PocketTrigger result = null;
			float num = 10000f;
			Vector3 zero = Vector3.zero;
			Vector3 zero2 = Vector3.zero;
			for (int i = 0; i < Pools.PocketTriggers.Count; i++)
			{
				PocketTrigger pocketTrigger = Pools.PocketTriggers[i];
				float num2 = Vector3.Distance(ball.position, pocketTrigger.GetRealPosition());
				if (pocketTrigger.PocketIndex == PocketIndexes.TopRight)
				{
					zero = pocketTrigger.GetRealPosition();
				}
				else if (pocketTrigger.PocketIndex == PocketIndexes.BottomLeft)
				{
					zero2 = pocketTrigger.GetRealPosition();
				}
				if (num2 < num)
				{
					result = pocketTrigger;
					num = num2;
				}
			}
			return result;
		}

		public Vector3 GetReboundHitPoint()
		{
			Vector3 inNormal = default(Vector3);
			for (int i = 0; i < cMsg.ballList.Count; i++)
			{
				PoolBall poolBall = cMsg.ballList[i];
				if (poolBall.BallState != PoolBall.State.IDLE)
				{
					continue;
				}
				PocketTrigger closestPocket = GetClosestPocket(poolBall);
				if (!(closestPocket != null))
				{
					continue;
				}
				Ray ray = new Ray(closestPocket.GetRealPosition(), poolBall.position - closestPocket.GetRealPosition());
				RaycastHit[] array = Physics.RaycastAll(ray);
				UnityEngine.Debug.DrawRay(ray.origin, ray.direction, Color.yellow);
				if (array.Length != 2)
				{
					continue;
				}
				for (int j = 0; j < array.Length; j++)
				{
					string name = array[j].transform.name;
					if (!name.Contains("Rail_"))
					{
						continue;
					}
					string value = name.Substring(5);
					if (value.ToEnum(TableBorder.None) != 0)
					{
						Vector3 normal = array[j].normal;
						float x = normal.x;
						Vector3 normal2 = array[j].normal;
						inNormal = new Vector3(x, 0f, normal2.z);
						Vector3 vector = Vector3.Reflect(ray.direction, inNormal);
						Vector3 point = array[j].point;
						Vector3 point2 = array[j].point;
						UnityEngine.Debug.DrawLine(point, new Vector3(0f, point2.y, 0f), Color.red);
						Ray ray2 = new Ray(array[j].point, vector);
						UnityEngine.Debug.DrawRay(array[j].point, vector, Color.black);
						if (Physics.Raycast(ray2, 100f, LayerMask.GetMask("WhiteBall")))
						{
							UnityEngine.Debug.Log("reflect cast hit white ball");
							return array[j].point;
						}
					}
				}
			}
			return Vector3.zero;
		}
	}

	protected class DecidedMessage
	{
		public Vector3 hitPoint;

		public Vector3 cueballPosition;

		public float powerScale;

		public bool drag;

		public PoolBall targetBall;

		public PocketTrigger targetPocket;

		public Dictionary<PoolBall, List<PocketTrigger>> considerBalls = new Dictionary<PoolBall, List<PocketTrigger>>();

		public List<KeyValuePair<PoolBall, Vector3>> shootableBalls = new List<KeyValuePair<PoolBall, Vector3>>();
	}

	protected class AIExecutor
	{
		public AIPlayer player;

		private DecidedMessage msg;

		private Queue<ExecuteBehaviour> behaviours;

		public bool deQueue;

		public AIExecutor(AIPlayer _player)
		{
			player = _player;
			behaviours = new Queue<ExecuteBehaviour>();
			deQueue = false;
		}

		public void SetDecision(DecidedMessage _msg)
		{
			msg = _msg;
			if (msg.drag)
			{
				if (Random.Range(0, 3) <= 2 && !GameManager.Rules.firstRound)
				{
					behaviours.Enqueue(new ExecuteDragThink(msg, player));
				}
				behaviours.Enqueue(new ExecuteDrag(msg, player));
			}
			behaviours.Enqueue(new ExecuteThink(msg, player, Random.Range(1.1f, 1.5f)));
			for (int i = 0; i < 3; i++)
			{
				if (Random.Range(0, 3) <= 2)
				{
					behaviours.Enqueue(new ExecuteAimThink(msg, player));
				}
			}
			behaviours.Enqueue(new ExecuteAim(msg, player));
			behaviours.Enqueue(new ExecuteThink(msg, player));
			behaviours.Enqueue(new ExecuteFire(msg, player));
		}

		public void Execute()
		{
			if (behaviours.Count != 0 && behaviours.Peek().Preparing())
			{
				behaviours.Dequeue().Do();
			}
		}
	}

	protected abstract class ExecuteBehaviour
	{
		protected DecidedMessage msg;

		protected AIPlayer player;

		public ExecuteBehaviour(DecidedMessage _msg, AIPlayer _player)
		{
			msg = _msg;
			player = _player;
		}

		public abstract void Do();

		public virtual bool Preparing()
		{
			return true;
		}
	}

	protected class ExecuteDrag : ExecuteBehaviour
	{
		public ExecuteDrag(DecidedMessage _msg, AIPlayer _player)
			: base(_msg, _player)
		{
		}

		public override void Do()
		{
			iTween.MoveTo(Pools.CueBall.gameObject, msg.cueballPosition, 1f);
		}
	}

	protected class ExecuteDragThink : ExecuteThink
	{
		public ExecuteDragThink(DecidedMessage _msg, AIPlayer _player)
			: base(_msg, _player)
		{
			m_ThinkTime = 0.5f;
		}

		public override void Do()
		{
			Vector3 b = new Vector3(Random.Range(0f, 0.5f), 0f, Random.Range(0f, 0.5f));
			iTween.MoveTo(Pools.CueBall.gameObject, msg.cueballPosition + b, 2f);
		}
	}

	protected class ExecuteThink : ExecuteBehaviour
	{
		protected float m_ThinkTime;

		public ExecuteThink(DecidedMessage _msg, AIPlayer _player)
			: base(_msg, _player)
		{
			m_ThinkTime = Random.Range(2, 3);
		}

		public ExecuteThink(DecidedMessage _msg, AIPlayer _player, float _thinkTime)
			: base(_msg, _player)
		{
			m_ThinkTime = _thinkTime;
		}

		public override void Do()
		{
		}

		public override bool Preparing()
		{
			m_ThinkTime -= Time.deltaTime;
			if (m_ThinkTime <= 0f)
			{
				return true;
			}
			return false;
		}
	}

	protected class ExecuteAimThink : ExecuteThink
	{
		public ExecuteAimThink(DecidedMessage _msg, AIPlayer _player)
			: base(_msg, _player)
		{
			m_ThinkTime = 1f;
		}

		public override void Do()
		{
			float rotationAngleAtWorld = BaseUIController.cueOperateArea.pointerOperation.GetRotationAngleAtWorld(msg.hitPoint + ((!(msg.targetBall != null)) ? Vector3.zero : (msg.targetBall.GetRadius() * Random.onUnitSphere)));
			Vector3 eulerAngles = Pools.Cue.transform.eulerAngles;
			Vector3 rotation = new Vector3(0f, eulerAngles.y + rotationAngleAtWorld, 0f);
			iTween.RotateTo(Pools.Cue.gameObject, rotation, 1f);
		}
	}

	protected class ExecuteAim : ExecuteBehaviour
	{
		public ExecuteAim(DecidedMessage _msg, AIPlayer _player)
			: base(_msg, _player)
		{
		}

		public override void Do()
		{
			GameManager.Rules.State = GlobalState.IDLE;
			float rotationAngleAtWorld = BaseUIController.cueOperateArea.pointerOperation.GetRotationAngleAtWorld(msg.hitPoint);
			Vector3 eulerAngles = Pools.Cue.transform.eulerAngles;
			Vector3 rotation = new Vector3(0f, eulerAngles.y + rotationAngleAtWorld, 0f);
			iTween.RotateTo(Pools.Cue.gameObject, rotation, 1f);
		}
	}

	protected class ExecuteFire : ExecuteBehaviour
	{
		private float m_Time = 0.2f;

		private float _Time;

		public ExecuteFire(DecidedMessage _msg, AIPlayer _player)
			: base(_msg, _player)
		{
		}

		public override void Do()
		{
			BaseUIController.cueAndLines.ReleaseCue();
		}

		public override bool Preparing()
		{
			BaseUIController.cueAndLines.AdjustingChange(Mathf.Lerp(0f, msg.powerScale, _Time / m_Time));
			_Time += Time.deltaTime;
			if (_Time > m_Time)
			{
				return true;
			}
			return false;
		}
	}

	protected AIExecutor m_Executor;

	protected AICollector m_Collector;

	protected AIDecider m_Decider;

	public static AIDifficulty difficulty = AIDifficulty.Medium;

	public static bool canReboundHit = true;

	public static bool canReboundPocket = true;

	public static float degreeOffset = 10f;

	[SerializeField]
	[Range(0f, 0.05f)]
	private float m_Deviation;

	public static BattleInfo curBattleInfo
	{
		get;
		set;
	}

	protected override void Awake()
	{
		base.Awake();
		m_Executor = new AIExecutor(this);
		m_Collector = new AICollector(this);
		m_Decider = new AIDecider(this);
	}

	public override void Begin()
	{
		if (GameManager.Rules.State != GlobalState.GAMEOVER)
		{
			BaseUIController.GlobalMask = true;
			DecidedMessage decision = m_Decider.Decide(m_Collector.Collect());
			m_Executor.SetDecision(decision);
		}
	}

	private void Update()
	{
		if (UnityEngine.Input.GetKeyDown(KeyCode.T))
		{
			UnityEngine.Debug.Log("press key T ");
		}
	}

	public override void End()
	{
		base.End();
	}

	public override void PlayerUpdate()
	{
		m_Executor.Execute();
	}
}
